﻿using AuthenticationDemo.Common;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace AuthenticationDemo.Services
{
    public class JWTService
    {
        public readonly JwtSecurityTokenHandler _jwtSecurity;

        public JWTService()
        {
            _jwtSecurity = new JwtSecurityTokenHandler();
        }
        public string GenerateUserToken(string username)
        {
            // 设置JWT参数
            string? secretKey = App.Configuration["Jwt:SecretKey"]; // 密钥
            string? issuer = App.Configuration["Jwt:Issuer"]; // 颁发者
            string? audience = App.Configuration["Jwt:Audience"]; // 接收者
            DateTime expiration = DateTime.UtcNow.AddMinutes(Convert.ToDouble(App.Configuration["Jwt:Expired"])); // 令牌过期时间

            if (!string.IsNullOrEmpty(secretKey) && !string.IsNullOrEmpty(issuer) && !string.IsNullOrEmpty(audience))
            {
                // 调用 GenerateToken 方法生成 JWT 令牌
                string jwtToken = GenerateToken(secretKey, issuer, audience, expiration, username);

                // 返回生成的 JWT 令牌
                return jwtToken;
            }

            return string.Empty;
        }

        public async Task<bool> VerifyJwtToken(string token)
        {
            try
            {
                var tokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(App.Configuration["Jwt:SecretKey"])), // 密钥    
                    ValidateIssuer = true,
                    ValidIssuer = App.Configuration["Jwt:Issuer"], // 发行者    
                    ValidateAudience = true,
                    ValidAudience = App.Configuration["Jwt:Audience"], // 受众    
                    ValidateLifetime = true, // 验证令牌是否在有效期内    
                    ClockSkew = TimeSpan.Zero // 允许的时间偏差    
                };

                // 解析并验证JWT令牌  
                var principal = _jwtSecurity.ValidateToken(token, tokenValidationParameters, out SecurityToken validatedToken);

                // 如果principal不为null，则验证成功  
                if (principal != null && validatedToken is JwtSecurityToken jwtSecurityToken && jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.OrdinalIgnoreCase))
                {
                    // 添加额外的逻辑，检查用户角色等
                    //var userRoles = principal.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value).ToList();
                    //if (userRoles.Contains("Admin"))
                    //{
                    //}
                    // 验证成功，返回true  
                    return true;
                }

                // 否则验证失败  
                return false;
            }
            catch (SecurityTokenExpiredException ex)
            {
                // 令牌已过期   
                return false;
            }
            catch (SecurityTokenInvalidSignatureException ex)
            {
                // 令牌签名不正确                 
                return false;
            }
            catch (Exception ex)
            {
                // 其他异常  
                return false;
            }
        }

        #region private method
        /// <summary>
        /// 
        /// </summary>
        /// <param name="secretKey">加密Key</param>
        /// <param name="issuer">发行（颁发）者</param>
        /// <param name="audience">接收者</param>
        /// <param name="expiration">令牌过期时间</param>
        /// <param name="username">用户名</param>
        /// <returns></returns>
        private static string GenerateToken(string secretKey, string issuer, string audience, DateTime expiration, string username)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            // 添加用户账户名到声明
            var claims = new[]
            {
                new Claim(ClaimTypes.Name, username),
                new Claim(ClaimTypes.Role, "Admin"),
                new Claim(ClaimTypes.Role, "G_Admin"),
            };

            var token = new JwtSecurityToken(
                issuer: issuer,
                audience: audience,
                claims: claims,
                expires: expiration,
                signingCredentials: credentials

            );

            return tokenHandler.WriteToken(token);
        }

        #endregion

    }
}